package cn.adviceclient.gui.click.advice;

import cn.adviceclient.features.module.Category;
import cn.adviceclient.features.module.Module;
import cn.adviceclient.features.module.ModuleManager;
import cn.adviceclient.features.module.impl.render.ClickGui;
import cn.adviceclient.features.value.AbstractSetting;
import cn.adviceclient.features.value.BooleanSetting;
import cn.adviceclient.features.value.ModeSetting;
import cn.adviceclient.features.value.StringSetting;
import cn.adviceclient.features.value.slider.DoubleSetting;
import cn.adviceclient.features.value.slider.FloatSetting;
import cn.adviceclient.features.value.slider.IntSetting;
import cn.adviceclient.features.value.slider.NumberSetting;
import cn.adviceclient.gui.font.Fonts;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.ScaledResolution;
import org.lwjgl.input.Keyboard;

import java.awt.*;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

public class AdviceClickGui extends GuiScreen {
    private final ClickGui clickGuiModule;

    // GUI dimensions
    private int guiX, guiY;
    private final int guiWidth = 500;
    private final int guiHeight = 300;
    private final int sidebarWidth = 120;

    // Colors
    private final int backgroundColor = new Color(17, 17, 17, 255).getRGB();
    private final int sidebarColor = new Color(22, 22, 22, 255).getRGB();
    private final int accentColor = new Color(170, 0, 0, 255).getRGB();
    private final int moduleColor = new Color(30, 30, 30, 255).getRGB();
    private final int moduleHoverColor = new Color(35, 35, 35, 255).getRGB();
    private final int moduleActiveColor = new Color(40, 40, 40, 255).getRGB();
    private final int textColor = Color.WHITE.getRGB();
    private final int subTextColor = new Color(170, 170, 170, 255).getRGB();

    // State
    private Category selectedCategory = Category.COMBAT;
    private Category previousCategory = Category.COMBAT;
    private Module selectedModule = null;
    private boolean bindingKey = false;
    private Module bindingModule = null;

    // Animation
    private long openTime;
    private float openAnimation = 0f;
    private float categoryIndicatorY = 40f;
    private float targetIndicatorY = 40f;

    // Settings
    private AbstractSetting<?> draggingSetting = null;

    public AdviceClickGui(ClickGui clickGuiModule) {
        super();
        this.clickGuiModule = clickGuiModule;
        this.openTime = System.currentTimeMillis();
    }

    @Override
    public void initGui() {
        super.initGui();
        ScaledResolution sr = new ScaledResolution(mc);
        this.guiX = (sr.getScaledWidth() - guiWidth) / 2;
        this.guiY = (sr.getScaledHeight() - guiHeight) / 2;
    }

    @Override
    public void drawScreen(int mouseX, int mouseY, float partialTicks) {
        // 动画
        long timeSinceOpen = System.currentTimeMillis() - openTime;
        openAnimation = Math.min(1f, timeSinceOpen / 300f);

        // 拖动数值设置
        if (draggingSetting != null && draggingSetting instanceof NumberSetting<?>) {
            NumberSetting<?> numberSetting = (NumberSetting<?>) draggingSetting;
            int settingsX = guiX + sidebarWidth + 150 + 20;
            int settingsWidth = guiWidth - sidebarWidth - 150 - 30;
            updateNumberSetting(numberSetting, mouseX, settingsX + 5, settingsWidth - 10);
        }

        // 分类指示动画
        int categoryIndex = 0;
        for (Category category : Category.values()) {
            if (category == selectedCategory) {
                targetIndicatorY = guiY + 40 + categoryIndex * 25;
                break;
            }
            categoryIndex++;
        }
        categoryIndicatorY += (targetIndicatorY - categoryIndicatorY) * 0.2f;

        // 背景
        ScaledResolution sr = new ScaledResolution(mc);
        drawRect(0, 0, sr.getScaledWidth(), sr.getScaledHeight(), 0x77000000);

        // 动画缩放
        int animatedWidth = (int)(guiWidth * openAnimation);
        int animatedHeight = (int)(guiHeight * openAnimation);
        int animatedX = guiX + (guiWidth - animatedWidth) / 2;
        int animatedY = guiY + (guiHeight - animatedHeight) / 2;
        drawRect(animatedX, animatedY, animatedX + animatedWidth, animatedY + animatedHeight, backgroundColor);

        if (openAnimation < 1f) return;

        // 侧边栏
        drawRect(guiX, guiY, guiX + sidebarWidth, guiY + guiHeight, sidebarColor);

        // 标题
        //fontRendererObj.drawString("AdviceNext", guiX + 10, guiY + 10, textColor);
        Fonts.interBold.get(20).drawString("AdviceNext", guiX + 10, guiY + 15, textColor);

        // 分类指示
        drawRect(guiX, (int)categoryIndicatorY, guiX + 3, (int)categoryIndicatorY + 20, accentColor);

        // 分类
        int categoryY = guiY + 40;
        for (Category category : Category.values()) {
            boolean isSelected = category == selectedCategory;
            fontRendererObj.drawString(category.getName(), guiX + 15, categoryY + 6,
                    isSelected ? accentColor : textColor);
            categoryY += 25;
        }

        // 模块
        int moduleX = guiX + sidebarWidth + 10;
        int moduleY = guiY + 10;
        int moduleWidth = 150;
        int moduleHeight = 20;
        for (Module module : ModuleManager.getModules()) {
            if (module.getCategory() == selectedCategory) {
                boolean isHovered = mouseX >= moduleX && mouseX <= moduleX + moduleWidth &&
                        mouseY >= moduleY && mouseY <= moduleY + moduleHeight;
                boolean isSelected = module == selectedModule;
                int bgColor = isSelected ? moduleActiveColor : (isHovered ? moduleHoverColor : moduleColor);
                drawRect(moduleX, moduleY, moduleX + moduleWidth, moduleY + moduleHeight, bgColor);

                fontRendererObj.drawString(module.getName(), moduleX + 5, moduleY + 6,
                        module.getEnabled() ? accentColor : textColor);

                String indicator = module.getEnabled() ? "ON" : "OFF";
                int indicatorWidth = fontRendererObj.getStringWidth(indicator);
                /*fontRendererObj.drawString(indicator, moduleX + moduleWidth - indicatorWidth - 5, moduleY + 6,
                        module.getEnabled() ? accentColor : subTextColor);*/
                Fonts.interBold.get(20).drawString(indicator, moduleX + moduleWidth - indicatorWidth - 5, moduleY + 6,
                        module.getEnabled()? accentColor : subTextColor);


                moduleY += moduleHeight + 5;
            }
        }

        // 设置面板
        if (selectedModule != null) {
            int settingsX = guiX + sidebarWidth + moduleWidth + 20;
            int settingsY = guiY + 10;
            int settingsWidth = guiWidth - sidebarWidth - moduleWidth - 30;

            fontRendererObj.drawString(selectedModule.getName() + " Settings", settingsX, settingsY, textColor);
            settingsY += 20;

            // 按键绑定
            drawRect(settingsX, settingsY, settingsX + settingsWidth, settingsY + 20, moduleColor);
            fontRendererObj.drawString("Key Bind", settingsX + 5, settingsY + 6, textColor);

            String keyName;
            if (bindingKey && bindingModule == selectedModule) {
                keyName = "Press a key...";
            } else {
                int key = selectedModule.getKey();
                keyName = key == -1 ? "None" : Keyboard.getKeyName(key);
                if (keyName == null) keyName = "Key " + key;
            }
            int keyWidth = fontRendererObj.getStringWidth(keyName);
            fontRendererObj.drawString(keyName, settingsX + settingsWidth - keyWidth - 5, settingsY + 6, subTextColor);
            settingsY += 25;

            Set<String> displayedSettings = new HashSet<>();
            for (AbstractSetting<?> setting : selectedModule.settings) {
                if (displayedSettings.contains(setting.getName())) continue;
                displayedSettings.add(setting.getName());

                drawRect(settingsX, settingsY, settingsX + settingsWidth, settingsY + 20, moduleColor);
                fontRendererObj.drawString(setting.getName(), settingsX + 5, settingsY + 6, textColor);

                if (setting instanceof BooleanSetting) {
                    BooleanSetting boolSetting = (BooleanSetting) setting;
                    String value = boolSetting.getValue() ? "ON" : "OFF";
                    int valueWidth = fontRendererObj.getStringWidth(value);
                    fontRendererObj.drawString(value, settingsX + settingsWidth - valueWidth - 5, settingsY + 6,
                            boolSetting.getValue() ? accentColor : subTextColor);
                } else if (setting instanceof ModeSetting) {
                    ModeSetting modeSetting = (ModeSetting) setting;
                    String value = modeSetting.getValue();
                    int valueWidth = fontRendererObj.getStringWidth(value);
                    fontRendererObj.drawString(value, settingsX + settingsWidth - valueWidth - 5, settingsY + 6, accentColor);
                } else if (setting instanceof NumberSetting<?>) {
                    NumberSetting<?> numberSetting = (NumberSetting<?>) setting;
                    String value = numberSetting.getValue().toString();
                    int valueWidth = fontRendererObj.getStringWidth(value);
                    fontRendererObj.drawString(value, settingsX + settingsWidth - valueWidth - 5, settingsY + 6, accentColor);

                    // slider
                    int sliderY = settingsY + 15;
                    int sliderWidth = settingsWidth - 10;
                    int sliderX = settingsX + 5;
                    drawRect(sliderX, sliderY, sliderX + sliderWidth, sliderY + 2, new Color(50, 50, 50, 255).getRGB());

                    double min = ((Number)numberSetting.getMin()).doubleValue();
                    double max = ((Number)numberSetting.getMax()).doubleValue();
                    double currentValue = ((Number)numberSetting.getValue()).doubleValue();
                    double percentage = (currentValue - min) / (max - min);
                    int progressWidth = (int)(sliderWidth * percentage);
                    drawRect(sliderX, sliderY, sliderX + progressWidth, sliderY + 2, accentColor);
                } else if (setting instanceof StringSetting) {
                    StringSetting stringSetting = (StringSetting) setting;
                    String value = stringSetting.getValue();
                    int valueWidth = fontRendererObj.getStringWidth(value);
                    fontRendererObj.drawString(value, settingsX + settingsWidth - valueWidth - 5, settingsY + 6, accentColor);
                }
                settingsY += 25;
            }
        }
    }

    @Override
    protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
        if (openAnimation < 1f) return;

        // 分类
        int categoryY = guiY + 40;
        for (Category category : Category.values()) {
            if (mouseX >= guiX && mouseX <= guiX + sidebarWidth && mouseY >= categoryY && mouseY <= categoryY + 20) {
                previousCategory = selectedCategory;
                selectedCategory = category;
                selectedModule = null;
                return;
            }
            categoryY += 25;
        }

        // 模块
        int moduleX = guiX + sidebarWidth + 10;
        int moduleY = guiY + 10;
        int moduleWidth = 150;
        int moduleHeight = 20;
        for (Module module : ModuleManager.getModules()) {
            if (module.getCategory() == selectedCategory) {
                if (mouseX >= moduleX && mouseX <= moduleX + moduleWidth && mouseY >= moduleY && mouseY <= moduleY + moduleHeight) {
                    if (mouseButton == 0) {
                        module.toggle();
                    } else if (mouseButton == 1) {
                        selectedModule = module;
                    }
                    return;
                }
                moduleY += moduleHeight + 5;
            }
        }

        // 设置
        if (selectedModule != null) {
            int settingsX = guiX + sidebarWidth + moduleWidth + 20;
            int settingsY = guiY + 10;
            int settingsWidth = guiWidth - sidebarWidth - moduleWidth - 30;
            settingsY += 20;

            if (mouseX >= settingsX && mouseX <= settingsX + settingsWidth && mouseY >= settingsY && mouseY <= settingsY + 20) {
                bindingKey = true;
                bindingModule = selectedModule;
                return;
            }
            settingsY += 25;

            Set<String> processedSettings = new HashSet<>();
            for (AbstractSetting<?> setting : selectedModule.settings) {
                if (processedSettings.contains(setting.getName())) continue;
                processedSettings.add(setting.getName());

                if (mouseX >= settingsX && mouseX <= settingsX + settingsWidth && mouseY >= settingsY && mouseY <= settingsY + 20) {
                    if (setting instanceof BooleanSetting) {
                        BooleanSetting boolSetting = (BooleanSetting) setting;
                        boolSetting.setValue(!boolSetting.getValue());
                    } else if (setting instanceof ModeSetting) {
                        ModeSetting modeSetting = (ModeSetting) setting;
                        modeSetting.cycle();
                    } else if (setting instanceof NumberSetting<?>) {
                        NumberSetting<?> numberSetting = (NumberSetting<?>) setting;
                        draggingSetting = setting;
                        updateNumberSetting(numberSetting, mouseX, settingsX + 5, settingsWidth - 10);
                    }
                    return;
                }
                settingsY += 25;
            }
        }

        super.mouseClicked(mouseX, mouseY, mouseButton);
    }

    @Override
    protected void mouseReleased(int mouseX, int mouseY, int state) {
        draggingSetting = null;
        super.mouseReleased(mouseX, mouseY, state);
    }

    private void updateNumberSetting(NumberSetting<?> setting, int mouseX, int sliderX, int sliderWidth) {
        double percentage = Math.max(0, Math.min(1, (double)(mouseX - sliderX) / sliderWidth));
        double min = ((Number)setting.getMin()).doubleValue();
        double max = ((Number)setting.getMax()).doubleValue();
        double newValue = min + (max - min) * percentage;

        if (setting instanceof IntSetting) {
            ((IntSetting)setting).setValue((int)newValue);
        } else if (setting instanceof FloatSetting) {
            ((FloatSetting)setting).setValue((float)newValue);
        } else if (setting instanceof DoubleSetting) {
            ((DoubleSetting)setting).setValue(newValue);
        }
    }

    @Override
    protected void keyTyped(char typedChar, int keyCode) throws IOException {
        if (bindingKey && bindingModule != null) {
            if (keyCode == 1) { // ESC
                bindingModule.bindKey(-1);
            } else {
                bindingModule.bindKey(keyCode);
            }
            bindingKey = false;
            bindingModule = null;
            return;
        }
        super.keyTyped(typedChar, keyCode);
    }

    @Override
    public void onGuiClosed() {
        super.onGuiClosed();
        clickGuiModule.disable();
    }
}